package mps

import (
	"errors"
	"fmt"
	mts20140618 "github.com/alibabacloud-go/mts-20140618/client"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/text/gstr"
	"github.com/gogf/gf/v2/util/gconv"
	"github.com/google/uuid"
	"net/url"
)

type snapshotService struct{}

type SnapshotConfig struct {
	SnapshotOutputFile *snapshotOutputFile `json:"OutputFile"`

	Time     *string `json:"Time"`
	Interval *string `json:"Interval"`
	Num      *string `json:"Num"`
	Height   *string `json:"Height"`
	Width    *string `json:"Width"`

	Format   string `json:"-"` // 不可序列化
	ImageDir string `json:"-"` // 不可序列化
}

type SnapshotInput struct {
	Bucket   string `json:"Bucket"`
	Location string `json:"Location"`
	Object   string `json:"Object"`
}

type snapshotOutputFile struct {
	OssLocation *string `json:"Location"` // 必要参数
	OssBucket   *string `json:"Bucket"`   // 必要参数
	OssObject   *string `json:"Object"`   // 必要参数
}

type SnapshotResponseEntity struct {
	Time       *string             `json:"Time,omitempty" xml:"Time,omitempty"`
	Interval   *string             `json:"Interval,omitempty" xml:"Interval,omitempty"`
	FrameType  *string             `json:"FrameType,omitempty" xml:"FrameType,omitempty"`
	Width      *string             `json:"Width,omitempty" xml:"Width,omitempty"`
	Height     *string             `json:"Height,omitempty" xml:"Height,omitempty"`
	OutputFile *snapshotOutputFile `json:"OutputFile,omitempty" xml:"OutputFile,omitempty" type:"Struct"`
	Num        *string             `json:"Num,omitempty" xml:"Num,omitempty"`
}

func (r *snapshotService) Query(requestParam *mpsRequestEntity, configParam *SnapshotConfig) (*mpsResponseEntity, error) {
	if requestParam == nil || requestParam.OssBucket == nil || requestParam.OssObject == nil {
		return nil, errors.New("mps invalid request param ,both bucket and object is nil")
	}

	var submitSnapshotJobRequest = new(mts20140618.SubmitSnapshotJobRequest)
	{
		defaultOssLocation := url.QueryEscape(Mps.cfg.OssLocation) // 指定位置
		if defaultOssLocation != *requestParam.OssLocation {
			return nil, errors.New("un support action")
		}

		var ossLocation string

		if requestParam.OssLocation == nil {
			ossLocation = defaultOssLocation
		} else {
			ossLocation = *requestParam.OssLocation
		}

		requestParam.OssLocation = &ossLocation
		// Input参数
		requestInputBS, _ := gjson.Encode(requestParam)
		requestInput := gconv.String(requestInputBS)
		submitSnapshotJobRequest.Input = &requestInput

		// 初始化
		if configParam == nil {
			configParam = new(SnapshotConfig)
			configParam.SnapshotOutputFile = new(snapshotOutputFile)
		}
		if configParam.SnapshotOutputFile == nil {
			configParam.SnapshotOutputFile = new(snapshotOutputFile)
		}

		// Snapshot config 参数
		configParam.SnapshotOutputFile.OssLocation = &defaultOssLocation

		// 默认 格式
		if configParam.Format == "" {
			configParam.Format = "jpg"
		}

		// 指定bucket
		if configParam.SnapshotOutputFile.OssBucket == nil {
			configParam.SnapshotOutputFile.OssBucket = &Mps.cfg.DefaultOutputBucket
		}

		// 默认文件名
		if configParam.SnapshotOutputFile.OssObject == nil {
			// 默认命名
			imageName := uuid.New().String()

			// 默认文件夹
			imageDir := gstr.SubStr(imageName, 0, 3)
			if configParam.ImageDir != "" {
				imageDir = configParam.ImageDir
			}

			// 默认命名
			imageObject := fmt.Sprintf("%s/%s", imageDir, imageName)
			if configParam.Interval != nil {
				imageObject += "_{Count}"
			}

			// 指定格式
			imageObject += "." + configParam.Format

			configParam.SnapshotOutputFile.OssObject = &imageObject
		}

		inputParam := SnapshotInput{
			Bucket:   *requestParam.OssBucket,
			Location: *requestParam.OssLocation,
			Object:   *requestParam.OssObject,
		}

		// json encode
		requestSnapshotInputBS, _ := gjson.Encode(inputParam)
		requestSnapshotInput := gconv.String(requestSnapshotInputBS)
		submitSnapshotJobRequest.Input = &requestSnapshotInput

		// 指定管道Id
		submitSnapshotJobRequest.SetPipelineId(Mps.cfg.PipelineId)

		// json encode
		requestSnapshotConfigBS, _ := gjson.Encode(configParam)
		requestSnapshotConfig := gconv.String(requestSnapshotConfigBS)

		submitSnapshotJobRequest.SnapshotConfig = &requestSnapshotConfig
	}

	client, _err := Mps.createClient()
	if _err != nil {
		return nil, _err
	}

	// 发起请求
	if respData, _err := client.SubmitSnapshotJob(submitSnapshotJobRequest); _err != nil {
		return nil, fmt.Errorf("mps submit snapshot job failed,err: %s", _err.Error())
	} else {

		// 结果参数
		snapshotConfig := respData.Body.SnapshotJob.SnapshotConfig

		return &mpsResponseEntity{
			RequestId: *respData.Body.RequestId,
			Data: &SnapshotResponseEntity{
				Time:      snapshotConfig.Time,
				Interval:  snapshotConfig.Interval,
				FrameType: snapshotConfig.FrameType,
				Width:     snapshotConfig.Width,
				Height:    snapshotConfig.Height,
				OutputFile: &snapshotOutputFile{
					OssLocation: snapshotConfig.OutputFile.Location,
					OssBucket:   snapshotConfig.OutputFile.Bucket,
					OssObject:   snapshotConfig.OutputFile.Object,
				},
				Num: snapshotConfig.Num,
			},
		}, nil
	}
}
